local japi = require 'jass.japi'
local slk = require 'jass.slk'
local runtime = require 'jass.runtime'

local upgrade = {
    
    __tostring = function(self) 
        return ('科技[%s]'):format(self.name) 
    end,

    __call = function(self, data) 
		for k,v in pairs(data) do 
			self[k] = v 
		end
		return self
    end,
}


upgrade.tooltips = {
    tip = function(self, level)
        if self.tips then 
            return self.tips[level] or self.tips[1]
        end 
        return self.tip
    end,
    ubertip = function(self, level)
        if self.ubertips then 
            return self.ubertips[level] or self.ubertips[1]
        end 
        return self.ubertip
    end,
    resource = function(self, level)
        return {
            gold = self.goldbase + self.goldmod * (level-1),
            wood = self.lumberbase + self.lumbermod * (level-1),
            cool = self.timebase + self.timemod * (level-1),
        }
    end,
}

upgrade.mapper = { }

function upgrade:__newindex(name, data)
    if name == "tech" and data and not upgrade.mapper[data] then 
        local code = FourCC(data)
        local tech = slk.upgrade[data]
        if tech then 
            self.maxlevel = tonumber(tech.maxlevel) or 1
            self.goldbase = tonumber(tech.goldbase) or 0
            self.lumberbase = tonumber(tech.lumberbase) or 0
            self.timebase = tonumber(tech.timebase) or 0
            self.goldmod = tonumber(tech.goldmod) or 0
            self.lumbermod = tonumber(tech.lumbermod) or 0
            self.timemod = tonumber(tech.timemod) or 0
            upgrade.mapper[data] = self
            upgrade.mapper[code] = self
        end
    end 
    rawset(self, name, data)
end

setmetatable(upgrade, upgrade)

ac.upgrade = setmetatable({}, {
    __index = upgrade,
    __call = function(self, name)
        local mt = {}
        self[name] = mt 
        mt.name = name 
        local data = ac.lni("tech", name)
		if data then 
            for k,v in pairs(data) do 
                mt[k] = v 
            end 
		end 
        setmetatable(mt, upgrade)
        return mt 
    end,
})

local mt = {}
upgrade.__index = mt 

-- 结构
mt.type = 'upgrade'

-- 科技ID 
mt.tech = nil

-- 提示
mt.tip = "科技"

-- 描述
mt.ubertip = ""

-- 等级
mt.level = 0

-- [获取ID]
function mt:get_id()
    return self.name 
end 

-- 派发事件
function mt:notify(name, ...)
    local func = self[name]
    if func then 
        return select(2, xpcall(func, runtime.error_handle, self, ...))
    end 
end 

-- 获取UI信息
function mt:get_tooltips(name)
    if self.tech and name and upgrade.tooltips[name] then 
        return upgrade.tooltips[name](self, ac.player.self:get_upgrade_level(self.name) + 1)
    end 
end

-- 设置玩家科技等级
function ac.player.__index:set_upgrade_level(name, level)
    local up = ac.upgrade[name]
    if up then 
        if up.tech then 
            jass.SetPlayerTechResearched(self.handle, FourCC(up.tech), level)
            self.upgrades[name] = jass.GetPlayerTechCount(self.handle, FourCC(up.tech), true)
        else 
            self.upgrades[name] = level
        end 
        up:notify("on_level_change", self)
        self:notify("玩家-科技等级变化", self, name)
    end 
end

-- 获取玩家科技等级
function ac.player.__index:get_upgrade_level(name)
    local up = ac.upgrade[name]
    if up then 
        if up.tech then 
            return jass.GetPlayerTechCount(self.handle, FourCC(up.tech), true)
        else 
            return self.upgrades[name] or 0
        end 
    end 
    return 0
end

-- 增加玩家科技等级
function ac.player.__index:add_upgrade_level(name, level)
    self:set_upgrade_level(name, self:get_upgrade_level(name) + level) 
end


ac.event.register("任意单位-研究科技完成", function()
    local handle = jass.GetTriggerUnit()
    ac.ignore_flag = true
    local unit = ac.unit.j_unit(handle)
    ac.ignore_flag = false
    local player = unit:get_owner()
    local techid = jass.GetResearched()
    local up = upgrade.mapper[techid]
    if up then 
        local name = up.name 
        local level = jass.GetPlayerTechCount(player.handle, techid, true)
        player.upgrades[name] = level
        up:notify("on_level_change", player)
        unit:notify('单位-研究科技完成', unit, up)
        player:notify("玩家-科技等级变化", player, name)
    end 
end)     

return upgrade